home *** CD-ROM | disk | FTP | other *** search
/ EnigmA Amiga Run 1996 March / EnigmA AMIGA RUN 05 (1996)(G.R. Edizioni)(IT)[!][issue 1996-03][Skylink CD IV].iso / earcd / program / ixemlsrc.lha / ixemul / library / _main.c < prev    next >
C/C++ Source or Header  |  1995-12-23  |  7KB  |  273 lines

  1. /*
  2.  *  This file is part of ixemul.library for the Amiga.
  3.  *  Copyright (C) 1991, 1992  Markus M. Wild
  4.  *
  5.  *  This library is free software; you can redistribute it and/or
  6.  *  modify it under the terms of the GNU Library General Public
  7.  *  License as published by the Free Software Foundation; either
  8.  *  version 2 of the License, or (at your option) any later version.
  9.  *
  10.  *  This library is distributed in the hope that it will be useful,
  11.  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  12.  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  13.  *  Library General Public License for more details.
  14.  *
  15.  *  You should have received a copy of the GNU Library General Public
  16.  *  License along with this library; if not, write to the Free
  17.  *  Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  18.  *
  19.  *  _main.c,v 1.1.1.1 1994/04/04 04:30:43 amiga Exp
  20.  *
  21.  *  _main.c,v
  22.  * Revision 1.1.1.1  1994/04/04  04:30:43  amiga
  23.  * Initial CVS check in.
  24.  *
  25.  *  Revision 1.3  1992/08/09  20:41:54  amiga
  26.  *  change to use 2.x header files by default
  27.  *  add option to ignore global environment (ix.ix_ignore_global_env).
  28.  *
  29.  *  Revision 1.2  1992/07/04  19:10:06  mwild
  30.  *  add call to ix_install_sigwinch().
  31.  *
  32.  * Revision 1.1  1992/05/17  21:01:29  mwild
  33.  * Initial revision
  34.  *
  35.  *
  36.  */
  37.  
  38. #define KERNEL
  39. #include "ixemul.h"
  40. #include "kprintf.h"
  41.  
  42. #include <dos/var.h>
  43. #include <workbench/startup.h>
  44. #include <dirent.h>
  45. #include <stdio.h>
  46. #include <string.h>
  47.  
  48. extern  struct ExecBase       *SysBase;
  49.  
  50. static char **__get_environ (void)
  51. {
  52.   static char *endmarker = 0;
  53.   char **env = &endmarker;
  54.   DIR *dp;
  55.   struct dirent *de;
  56.   int num_env, num_local = 0;
  57.   char **cp;
  58.  
  59.   /* 2.0 local environment overrides 1.3 global environment */
  60.       struct Process *me = (struct Process *) FindTask (0);
  61.       struct LocalVar *lv, *nlv;
  62.  
  63.       /* count total number of local variables (skip aliases) */
  64.       for (num_local = 0, 
  65.          lv  = (struct LocalVar *) me->pr_LocalVars.mlh_Head;
  66.        (nlv = (struct LocalVar *) lv->lv_Node.ln_Succ);
  67.        lv  = nlv)
  68.     if (lv->lv_Node.ln_Type == LV_VAR)
  69.       num_local ++;
  70.       
  71.       if ((cp = (char **) syscall (SYS_malloc, (num_local + 1) * 4)))
  72.     {
  73.       env = cp;
  74.  
  75.       for (lv  = (struct LocalVar *) me->pr_LocalVars.mlh_Head;
  76.            (nlv = (struct LocalVar *) lv->lv_Node.ln_Succ);
  77.            lv  = nlv)
  78.         {
  79.           /* I'm not interested in aliases, really not ;-)) */
  80.           if (lv->lv_Node.ln_Type != LV_VAR)
  81.             continue;
  82.         
  83.           /* NAME=CONTENTS\0 */
  84.           *cp = (char *) syscall (SYS_malloc, (strlen (lv->lv_Node.ln_Name) 
  85.                            + 1 + lv->lv_Len + 1));
  86.           if (*cp)
  87.         sprintf (*cp, "%s=%*.*s", lv->lv_Node.ln_Name, 
  88.              (int)lv->lv_Len, (int)lv->lv_Len, lv->lv_Value);
  89.  
  90.           else
  91.         break;
  92.  
  93.           cp ++;
  94.         }
  95.  
  96.       *cp = 0;
  97.     }
  98.       else
  99.     num_local = 0;
  100.  
  101.   if (ix.ix_flags & ix_ignore_global_env)
  102.     return env;
  103.  
  104.   /* now go for global variables */
  105.   
  106.   if ((dp = (DIR *) syscall (SYS_opendir, "ENV:")))
  107.     {
  108.       /* first count how many entries we have */
  109.       for (num_env = 0; syscall(SYS_readdir, dp); num_env++) ;
  110.       
  111.       /* skip . and .. */
  112.       syscall (SYS_rewinddir, dp);
  113.       if ((de = (struct dirent *) syscall (SYS_readdir, dp)) 
  114.       && de->d_namlen == 1 && de->d_name[0] == '.' && --num_env &&
  115.       (de = (struct dirent *) syscall (SYS_readdir, dp)) 
  116.       && de->d_namlen == 2 && de->d_name[0] == '.' && de->d_name[1] == '.')
  117.     {
  118.       num_env --;
  119.       de = (struct dirent *) syscall (SYS_readdir, dp);
  120.     }
  121.  
  122.       if (num_local)
  123.     {
  124.       /* only (!) in this case is `env' allocated and not static */
  125.       char **tmp = (char **) syscall (SYS_realloc, 
  126.                       env, (num_local + num_env + 1) * 4);
  127.       if (tmp)
  128.         {
  129.           cp = tmp + (cp - env);
  130.           env = tmp;
  131.         }
  132.       else
  133.         /* out of memory !!! */
  134.         return &endmarker;
  135.     }
  136.       else
  137.     {
  138.       if ((cp = (char **) syscall (SYS_malloc, (num_env + 1) * 4)))
  139.         env = cp;
  140.       else
  141.         /* out of memory !!! */
  142.         return &endmarker;
  143.     }
  144.       
  145.  
  146.       for (;de; de = (struct dirent *) syscall (SYS_readdir, dp))
  147.     {
  148.       struct stat stb;
  149.       int len = 0;
  150.       char envfile[MAXPATHLEN];
  151.  
  152.       /* If this variable already exists locally, skip it */
  153.       if (FindVar (de->d_name, GVF_LOCAL_ONLY))
  154.         continue;
  155.  
  156.       /* Don't include variables with funny names, and don't include
  157.          multiline variables either, they totally confuse ksh.. */
  158.       if (strchr(de->d_name, '.'))
  159.         continue;
  160.  
  161.       sprintf (envfile, "ENV:%s", de->d_name);
  162.  
  163.       if (syscall(SYS_stat, envfile, &stb) == 0)
  164.         {
  165.           len = stb.st_size;
  166.           /* skip directories... shudder */
  167.           if (! S_ISREG (stb.st_mode))
  168.             continue;
  169.         }
  170.  
  171.       /* NAME=CONTENTS\0 */
  172.       *cp = (char *) syscall (SYS_malloc, de->d_namlen + 1 + len + 1);
  173.       if (*cp)
  174.         {
  175.           int written = sprintf (*cp, "%s=", de->d_name);
  176.           int fd;
  177.  
  178.           if (len)
  179.         {
  180.           fd = syscall(SYS_open, envfile, 0);
  181.           if (fd >= 0)
  182.             {
  183.               written += syscall(SYS_read, fd, *cp + written, len);
  184.               (*cp)[written] = 0;
  185.               if ((*cp)[--written] == '\n')
  186.             (*cp)[written] = 0;
  187.               syscall(SYS_close, fd);
  188.             }
  189.             
  190.           /* now filter out those multiliners (that is, 
  191.              variables containing \n, you can have variables
  192.              as long as want, but don't use \n... */
  193.           if (strchr(*cp, '\n'))
  194.             {
  195.               syscall (SYS_free, *cp);
  196.               continue;
  197.             }
  198.         }
  199.         }
  200.       else
  201.         break;
  202.  
  203.       cp ++;
  204.     }
  205.  
  206.       *cp = 0;
  207.  
  208.       syscall (SYS_closedir, dp);
  209.       
  210.       return env;
  211.     }
  212.   else
  213.     /* `panic!', no ENV: logical ! */
  214.     return &endmarker;
  215. }
  216.  
  217.  
  218. /* smells abit kludgy I know.. but can live with quite few variables in
  219.  * the user area 
  220.  */
  221.  
  222. int
  223. _main (union { char *_aline; struct WBStartup *_wb_msg; } a1,
  224.        union { int   _alen;  char *_def_window;         } a2,
  225.        int (* main(int, char **, char **)))
  226. #define aline           a1._aline
  227. #define alen            a2._alen
  228. #define wb_msg          a1._wb_msg
  229. #define def_window      a2._def_window
  230. {
  231.   struct Process        *me             = (struct Process *)SysBase->ThisTask;
  232.   char                  **argv, **env;
  233.   int                   argc;
  234.  
  235.   KPRINTF (("entered __main()\n"));
  236.   if (! me->pr_CLI)
  237.     {
  238.       /* Workbench programs expect to have their CD where the executed
  239.        * program lives. */
  240.       if (wb_msg->sm_ArgList)
  241.     {
  242.       CurrentDir (wb_msg->sm_ArgList->wa_Lock);
  243.       syscall (SYS__wb_parse, me, wb_msg, def_window);
  244.     }
  245.       /* argc==0: this means, that argv is really a WBenchMsg, not a vector */
  246.       argc = 0;
  247.       argv = (char **) wb_msg;
  248.     }
  249.   else
  250.     {
  251.       /* if we were started from the CLI, alen & aline are valid and
  252.        * should now be split into arguments. This is done by the
  253.        * function "_cli_parse()", which does wildcard expansion if not
  254.        * disabled (see cli_parse.c). */
  255.       _cli_parse (me, alen, aline, &argc, &argv);
  256.       if (is_ixconfig(argv[0]))
  257.         return 10;
  258.     }
  259.  
  260.   env = __get_environ ();
  261.  
  262.   /* this is not really the right thing to do, the user should call
  263.      ix_get_vars2 () to initialize environ to the address of the variable
  264.      in the calling program. However, this setting guarantees that 
  265.      the user area entry is valid for getenv() calls. */
  266.   u.u_environ = &env;
  267.  
  268.   ix_install_sigwinch ();
  269.  
  270.   syscall (SYS_exit, main (argc, argv, env));
  271.   return 0;
  272. }
  273.